#region License
// PostService.cs
// 
// Copyright (c) 2012 Xoqal.com
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// 
// http://www.apache.org/licenses/LICENSE-2.0
// 
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#endregion

namespace Kaqaz.Services
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using Xoqal.Data.Linq;
    using Xoqal.Data.Models;

    public class PostService : IPostService
    {
        private readonly Data.IPostRepository postRepository;
        private readonly Data.ICommentRepository commentRepository;
        private readonly TagService tagService;

        /// <summary>
        /// Initializes a new instance of the <see cref="PostService" /> class.
        /// </summary>
        /// <param name="postRepository">The post repository.</param>
        /// <param name="commentRepository">The comment repository.</param>
        /// <param name="tagService">The tag service.</param>
        public PostService(
            Data.IPostRepository postRepository, 
            Data.ICommentRepository commentRepository, 
            TagService tagService)
        {
            this.postRepository = postRepository;
            this.commentRepository = commentRepository;
            this.tagService = tagService;
        }

        /// <summary>
        /// Gets the posts.
        /// </summary>
        /// <returns></returns>
        public IPaginated<Models.Post> GetPosts(int page, string tag, int pageSize)
        {
            var query = this.postRepository.Query;

            if (!string.IsNullOrWhiteSpace(tag))
            {
                tag = tag.Trim();
                query = query.Where(p => p.Tags.Any(t => t.Name.Equals(tag, StringComparison.InvariantCultureIgnoreCase)));
            }

            var data = query.ToPage((page - 1) * pageSize, pageSize, null)
                .Select(p =>
                    new
                    {
                        Post = p,
                        VisibleComments = p.Comments.Where(c => !p.NeedCommentApprove || (c.IsApproved || c.IsAuthorComment))
                    })
                .AsEnumerable()
                .Select(p => new Models.Post(p.Post) { VisibleComments = p.VisibleComments });

            return new Paginated<Models.Post>(data, query.Count(), page, pageSize);
        }

        /// <summary>
        /// Sets the post entity data according to its model equivalent.
        /// </summary>
        /// <param name="model">The post model.</param>
        /// <returns></returns>
        public void SetPostData(Models.Post model, Entities.Post entity)
        {
            entity.Title = model.Title;
            entity.Summary = model.Summary;
            entity.Content = model.Content;
            entity.IsCommentsEnable = model.IsCommentsEnable;
            entity.NeedCommentApprove = model.NeedCommentApprove;
            entity.LastUpdateTime = model.LastUpdateTime;

            if (model.CreateTime.HasValue)
            {
                entity.CreateTime = model.CreateTime.Value;
            }

            entity.Tags.Clear();
            
            // Tags
            if (!string.IsNullOrWhiteSpace(model.TagsString))
            {
                // Get or insert all tags and add them to the post entity.
                foreach (var tag in this.tagService.GetTags(model.TagsString))
                {
                    entity.Tags.Add(tag);
                }
            }
        }

        /// <summary>
        /// Gets the visible comments.
        /// </summary>
        /// <param name="post">The post.</param>
        /// <returns></returns>
        public IEnumerable<Entities.Comment> GetVisibleComments(Entities.Post post)
        {
            var q = this.commentRepository.Query.Where(c => c.PostId == post.Id);

            if (post.NeedCommentApprove)
            {
                q = q.Where(c => c.IsApproved || c.IsAuthorComment);
            }

            return q;
        }
    }
}
